package jmine.tec.services.callable;

import java.io.ByteArrayInputStream;
import java.io.Serializable;
import java.util.concurrent.Callable;

import jmine.tec.environment.db.DBEnvironment;
import jmine.tec.environment.utils.SpringConfigFactory;
import jmine.tec.environment.utils.TestDBApplicationContext;
import jmine.tec.services.ServicesController;
import jmine.tec.services.environment.RefDBEnvironment;

import org.springframework.beans.factory.BeanFactory;

import bancosys.tec.persist.authorization.AuthorizationStatus;
import bancosys.tec.utils.db.descriptor.FlatReferenceDatabaseBuilder.ReferenceDatabaseDescriptionType;

/**
 * O Callable que executa um arquivo de serviços.
 * 
 * @author Cesar Olmos
 */
public class ServicesCallable implements Callable<ServicesResult>, Serializable {

    private String fileName;

    private byte[] fileData;

    private String[] resourcesBaseReferencia;

    private ReferenceDatabaseDescriptionType referenceDatabaseDescriptionType;

    private String springMainXMLFilename;

    /**
     * Construtor.
     * 
     * @param fileName o nome do arquivo.
     * @param fileData o conteúdo do arquivo.
     * @param resourcesBaseReferencia os recursos da base de referência.
     * @param referenceDatabaseDescriptionType o tipo da base de referência.
     * @param springMainXMLFilename o arquivo principal do Spring.
     */
    public ServicesCallable(String fileName, byte[] fileData, String[] resourcesBaseReferencia,
            ReferenceDatabaseDescriptionType referenceDatabaseDescriptionType, String springMainXMLFilename) {
        this.fileName = fileName;
        this.fileData = fileData;
        this.resourcesBaseReferencia = resourcesBaseReferencia;
        this.referenceDatabaseDescriptionType = referenceDatabaseDescriptionType;
        this.springMainXMLFilename = springMainXMLFilename;
    }

    /**
     * Executa o arquivo de serviços.
     * 
     * @return o resultado da execução.
     */
    public ServicesResult call() {
        SpringConfigFactory configFactory = new SpringConfigFactory();
        BeanFactory bf = new TestDBApplicationContext(this.springMainXMLFilename, configFactory.getApplicationContext()).getBeanFactory();
        DBEnvironment env =
                new RefDBEnvironment(bf, this.springMainXMLFilename, configFactory.getDatabaseServerType(), this.resourcesBaseReferencia,
                        this.referenceDatabaseDescriptionType);
        env.start();

        AuthorizationStatus previousAuthorizationStatus = env.getHelper().getThreadAuthorizationStatus();
        env.getHelper().setThreadAuthorizationStatus(AuthorizationStatus.DISABLED);

        ServicesResult result = this.execute(bf);

        env.getHelper().setThreadAuthorizationStatus(previousAuthorizationStatus);
        return result;
    }

    /**
     * Executa o arquivo de serviços.
     * 
     * @param bf a bean factory.
     * @return o resultado da execução.
     */
    protected ServicesResult execute(BeanFactory bf) {
        try {
            this.getServicesController(bf).executeServices(this.fileName, new ByteArrayInputStream(this.fileData));
            return new ServicesResult(true, null);
        } catch (Throwable t) {
            return new ServicesResult(false, t);
        }
    }

    /**
     * Return the ServicesController
     * 
     * @param bf a bean factory.
     * @return the ServicesController
     */
    private ServicesController getServicesController(BeanFactory bf) {
        return (ServicesController) bf.getBean("servicesController", ServicesController.class);
    }
}
